<template>
  <div class="box-selection">
    <div class="infomation">{{ infomation }} --- 这是替换国内的高德地图 国外很多地图对祖国的边界和领土都存在偏差，openlayer上的数据原有些恶心</div>
    <div class="map" id="map"></div>
  </div>
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';

import 'ol/ol.css';
import GeoJSON from 'ol/format/GeoJSON';
import Map from 'ol/Map';
import View from 'ol/View';
import { DragBox, Select } from 'ol/interaction';
import { OSM, Vector as VectorSource } from 'ol/source';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import { platformModifierKeyOnly } from 'ol/events/condition';
import TileImage from 'ol/source/TileImage';

@Component({
  components: {},
})
export default class BoxSelection extends Vue {
  private map: any = null;
  private infomation: string = 'No countries selected';
  // 国边界线坐标集合
  private vectorSource = new VectorSource({
    url: 'https://openlayers.org/en/latest/examples/data/geojson/countries.geojson',
    format: new GeoJSON(),
  });

  private select = new Select();
  private selectedFeatures = this.select.getFeatures();
  private dragBox = new DragBox({
    condition: platformModifierKeyOnly,
  });
  public dragFunction() {
    this.dragBox.on('boxend', () => {
      // features that intersect the box geometry are added to the
      // collection of selected features

      // if the view is not obliquely rotated the box geometry and
      // its extent are equalivalent so intersecting features can
      // be added directly to the collection
      let rotation = this.map.getView().getRotation();
      let oblique = rotation % (Math.PI / 2) !== 0;
      let candidateFeatures = oblique ? [] : this.selectedFeatures;
      let extent = this.dragBox.getGeometry().getExtent();
      this.vectorSource.forEachFeatureIntersectingExtent(extent, function (feature: any) {
        candidateFeatures.push(feature);
      });

      // when the view is obliquely rotated the box extent will
      // exceed its geometry so both the box and the candidate
      // feature geometries are rotated around a common anchor
      // to confirm that, with the box geometry aligned with its
      // extent, the geometries intersect
      if (oblique) {
        let anchor = [0, 0];
        let geometry = this.dragBox.getGeometry().clone();
        geometry.rotate(-rotation, anchor);
        let extent$1 = geometry.getExtent();
        candidateFeatures.forEach((feature: any) => {
          let geometry = feature.getGeometry().clone();
          geometry.rotate(-rotation, anchor);
          if (geometry.intersectsExtent(extent$1)) {
            this.selectedFeatures.push(feature);
          }
        });
      }
    });

    // clear selection when drawing a new box and when clicking on the map
    this.dragBox.on('boxstart', () => {
      this.selectedFeatures.clear();
    });
  }
  public changeInfomations() {
    this.selectedFeatures.on(['add', 'remove'], () => {
      let names = this.selectedFeatures.getArray().map(function (feature: any) {
        return feature.get('name');
      });
      if (names.length > 0) {
        this.infomation = names.join(', ');
      } else {
        this.infomation = 'No countries selected';
      }
    });
  }
  public mounted() {
    this.createMap(() => {
      this.map.addInteraction(this.select);
      this.map.addInteraction(this.dragBox);
      this.dragFunction();
      this.changeInfomations();
    });
  }

  public createMap(cb: any) {
    this.map = new Map({
      layers: [
        new TileLayer({
          source: new TileImage({
            tileUrlFunction: this.tileFunction,
            attributions:
              'Tiles © <a href="https://www.amap.com/">高德地图</a>',
          }),
        }),
        new VectorLayer({
          source: this.vectorSource,
        }),
      ],
      target: 'map',
      view: new View({
        center: [0, 0],
        zoom: 2,
        constrainRotation: 16,
      }),
    });
    if (this.map) {
      cb && cb();
    }
  }
  public tileFunction(tileCoord: any) {
    let [z, x, y] = tileCoord;
    return `https://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=${x}&y=${y}&z=${z}`;
  }
}
</script>
<style lang="less" scoped>
.map {
  height: calc(100vh - 274px);
  width: 100%;
}
</style>